import {
  Event,
  EventEmitter,
  TreeDataProvider,
  TreeItem,
  window,
  workspace,
} from "vscode";
import { getGzData } from "./api";
import { updateFund } from "./utils";
import FundItem from "./utilClass/FundItem";

export default class DataProvider implements TreeDataProvider<FundInfo> {
  public refreshEvent: EventEmitter<FundInfo | null> =
    new EventEmitter<FundInfo | null>();

  readonly onDidChangeTreeData: Event<FundInfo | null> =
    this.refreshEvent.event;

  refresh() {
    // 更新视图
    this.refreshEvent.fire(null);
  }

  private order: number;

  constructor() {
    this.order = -1;
  }

  /**
   * 返回视图单行的UI数据，需要对其进行实例化
   * @param element
   * @returns
   */
  getTreeItem(info: FundInfo): FundItem {
    // 提取出名字和涨跌幅，展示出来
    return new FundItem(info);
  }

  /**
   * 该方法有一个可选参数 element ，返回的是 element 下的所有子元素，如果element为空，则返回根节点的所有子元素
   * @returns
   */
  async getChildren(): Promise<FundInfo[]> {
    const { order } = this;
    const viewData: string[] = workspace
      .getConfiguration()
      .get("fund-watch.favorites", []);
    const fundInfos: FundInfo[] = await getGzData([...viewData]);

    return fundInfos.sort(
      ({ changeRate: a = 0 }, { changeRate: b = 0 }) =>
        (+a >= +b ? 1 : -1) * order
    );
  }

  /**
   * 添加一个自选基金到列表中
   * @returns
   */
  async addFund(): Promise<void> {
    const res = await window.showInputBox({
      title: "添加基金",
      value: "",
      valueSelection: [20, -1],
      prompt: "添加自选基金",
      placeHolder: "输入基金代码，多个基金代码使用分号隔开",
      // 这里不适用验证了，总感觉严重不正确，在下面拿到结果之后再验证
      // validateInput: (inputCode: string) => {
      //   const reg = /^(\d{6}\;?)+\d{6}$/;
      //   if (reg.test(inputCode)) {
      //     return "输入的基金代码格式不正确";
      //   }
      //   return null;
      // },
    });
    if (res !== undefined) {
      const reg = /^(\d{6}\;)*\d{6}$/;
      if (!reg.test(res)) {
        window.showErrorMessage("输入的基金代码有误");
        return;
      }
      const codeList: string[] = res.split(";") || [];
      const result = await getGzData([...codeList]);
      if (result && result.length) {
        const codeListByResult: string[] = result.map((i) => i.code);
        // 这里一定先await，要下等config数据更新完毕之后才刷新，不然 refreshEvent 时拿到的是旧数据
        await updateFund(codeListByResult);
        // 更新视图
        this.refresh();
        return;
      }
      window.showWarningMessage("未找到此基金代码对应的基金");
    }
  }

  /**
   * 更改排序
   */
  changeOrder(): void {
    this.order *= -1;
    this.refresh();
  }
}
